<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>flow-chart</title>
    <style>
      body {
        -moz-user-select: none;
        -o-user-select: none;
        -khtml-user-select: none;
        -webkit-user-select: none;
        -ms-user-select: none;
        user-select: none;
      }
    </style>
  </head>
  <body>
    <div>
      <button id="rect">rect</button>
      <button id="circle">circle</button>
      <button id="line">line</button>
      <button id="diamond">diamond</button>
      <button id="text">text</button>
      文本颜色：<input type="color" id="textColor" /> 线颜色：<input
        type="color"
        id="strokeColor"
      />
      填充颜色：<input type="color" value="#ffffff" id="fillColor" />
    </div>
    <div style="border: 1px solid #000; margin-top: 10px">
      <canvas id="c1" width="1680px" height="800px"></canvas>
    </div>
    <script src="./utils.js"></script>
    <script src="./shape.js"></script>
    <script>
      /** @type {HTMLCanvasElement} */
      const shapes = new Shapes();
      // 获取元素
      const rectBtn = document.getElementById("rect");
      const circleBtn = document.getElementById("circle");
      const lineBtn = document.getElementById("line");
      const diamondBtn = document.getElementById("diamond");
      const textBtn = document.getElementById("text");
      const textColorInput = document.getElementById("textColor");
      const strokeColorInput = document.getElementById("strokeColor");
      const fillColorInput = document.getElementById("fillColor");
      // 定义颜色值
      let textColor = textColorInput.value;
      let strokeColor = strokeColorInput.value;
      let fillColor = fillColorInput.value;
      // 定义删除菜单
      let menuItem = null;
      const c1 = document.getElementById("c1");
      const ctx = c1.getContext("2d");
      // 定义拉伸方向的值
      let resizeDirection = "";
      // 定义是否在拉伸点上的开关
      let isResizing = false;
      // 定义拉伸点存储对象
      let resizePoint = null;
      // 绑定事件
      textColorInput.addEventListener("change", (e) => {
        console.log("textColor", e.target.value);
        textColor = e.target.value;
      });
      strokeColorInput.addEventListener("change", (e) => {
        console.log("strokeColor", e.target.value);
        strokeColor = e.target.value;
      });
      fillColorInput.addEventListener("change", (e) => {
        console.log("fillColor", e.target.value);
        fillColor = e.target.value;
      });
      rectBtn.addEventListener("click", () => {
        // shapes.curShape = "rect";
        const shape = new shapes["rect"]({ startX: 0, startY: 0 });
        shapes.shapeList.push(shape);
        shapes.render(ctx);
      });
      circleBtn.addEventListener("click", () => {
        // shapes.curShape = "circle";
        const shape = new shapes["circle"]({ startX: 50, startY: 50 });
        shapes.shapeList.push(shape);
        shapes.render(ctx);
      });
      lineBtn.addEventListener("click", () => {
        // shapes.curShape = "line";
        const shape = new shapes["line"]({ startX: 10, startY: 10 });
        shapes.shapeList.push(shape);
        shapes.render(ctx);
      });
      diamondBtn.addEventListener("click", () => {
        // shapes.curShape = "diamond";
        const shape = new shapes["diamond"]({ startX: 100, startY: 50 });
        shapes.shapeList.push(shape);
        shapes.render(ctx);
      });
      textBtn.addEventListener("click", () => {
        // shapes.curShape = "text";
        const shape = new shapes["text"]({
          startX: 50,
          startY: 50,
          endX: 150,
          endY: 82,
        });
        shapes.textList.push(shape);
        shapes.render(ctx);
      });
      c1.addEventListener("click", (e) => {
        const x = e.offsetX;
        const y = e.offsetY;
        const index = getFirstTouchShapeIndex(x, y, shapes);
        if (index > -1) {
          const curentShape = shapes.list[index];
          curentShape.strokeColor = strokeColor;
          curentShape.fillColor = fillColor;
          curentShape.textColor = textColor;
          shapes.render(ctx);
        }
      });
      c1.addEventListener("dblclick", (e) => {
        e.stopPropagation();
        const x = e.offsetX;
        const y = e.offsetY;
        console.log("x", x, "y", y);
        const index = getFirstTouchShapeIndex(x, y, shapes);
        if (index > -1) {
          // 在图形内
          console.log("双击 在图形内");
          shapes.isDraging = true;
          const curentShape = shapes.list[index];
          const position = c1.getBoundingClientRect();
          let left = curentShape.startX + curentShape.width / 2;
          let top = curentShape.startY + curentShape.height / 2;
          if (!["rect", "text"].includes(curentShape.shape)) {
            left = curentShape.startX;
            top = curentShape.startY;
          }
          insertInput({
            curentShape,
            position,
            shapes,
            left,
            top,
          });
        }
        shapes.isStart = false;
        shapes.curIndex = -1;
      });
      // 鼠标右键
      /* c1.addEventListener("contextmenu", function (event) {
        // 阻止默认的右键菜单
        event.preventDefault();
        const x = event.offsetX;
        const y = event.offsetY;
        console.log("x", x, "y", y);
        console.log("clientX", event.clientX, "clientY", event.clientY);
        // 创建一个新的菜单项
        // 创建一个新的菜单项
        menuItem = document.createElement("ul");
        menuItem.textContent = "删除";
        menuItem.dataset.name = 'menuItem'
        menuItem.style.position = "absolute";
        menuItem.style.top = event.clientY + "px";
        menuItem.style.left = event.clientX + "px";
        menuItem.style.padding = "10px";
        menuItem.style.backgroundColor = "lightgray";
        menuItem.style.cursor = "pointer";
        document.body.appendChild(menuItem);

        // 添加点击事件处理程序
        menuItem.addEventListener("click", function () {

        })

      }); */
      // 鼠标左键
      c1.addEventListener("mousedown", (e) => {
        const x = e.offsetX;
        const y = e.offsetY;
        console.log("x", x, "y", y);
        const index = getFirstTouchShapeIndex(x, y, shapes);
        if (index > -1) {
          console.log("在图形内");
          // shapes.isDraging = true;
          shapes.curIndex = index;
          const curentShape = shapes.list[index];
          // 排他法
          shapes.list.forEach((item) => {
            item.select = false;
            item.render = item.draw;
          });
          curentShape.render = curentShape.pre;
          curentShape.select = true;
          // 鼠标是否在拉伸点上
          shapes.stretch = isResizing;
          shapes.isDraging = !isResizing;
        } else {
          console.log("不在图形内");
          // 恢复图形默认渲染函数
          shapes.list.forEach((item) => {
            item.select = false;
            item.render = item.draw;
          });
          shapes.isDraging = false;
          shapes.curIndex = -1;
        }
        shapes.render(ctx);
        shapes.startX = x;
        shapes.startY = y;
        shapes.isStart = true;
      });
      // 鼠标移动
      c1.addEventListener("mousemove", (e) => {
        const x = e.offsetX;
        const y = e.offsetY;
        if (!shapes.isStart) {
          // 鼠标未按下，判断鼠标是否悬浮在某个图形之上
          const index = getFirstTouchShapeIndex(x, y, shapes);
          console.log("index", index);
          if (index > -1) {
            // 鼠标悬浮在图形上
            console.log("鼠标悬浮在图形上");
            // 更改绘制悬浮图形方法
            const curentShape = shapes.list[index];
            curentShape.render = curentShape.pre;
            // 先重置拉伸点信息状态
            isResizing = false;
            resizePoint = null;
            resizeDirection = "";
            // 判断鼠标是否在拉伸点上
            curentShape.vertices.forEach((item) => {
              const distance = Math.sqrt(
                Math.pow(item.x - x, 2) + Math.pow(item.y - y, 2)
              );
              // console.log("distance", distance);
              if (distance < 15) {
                isResizing = true;
                resizePoint = item;
              }
            });
            // 改变鼠标形状
            if (isResizing) {
              // 区分直线
              const { cursor, direction } =
                curentShape.stretchDirection(resizePoint);
              c1.style.cursor = cursor;
              resizeDirection = direction;
              // console.log("resizeDirection", resizeDirection);
            } else {
              c1.style.cursor = "move";
            }
            // 更新悬浮图形
            shapes.render(ctx);
            // 记录更新图形
            shapes.curIndex = index;
          } else if (shapes.curIndex > -1) {
            c1.style.cursor = "default";
            // 鼠标悬浮在图形外，绘制老图形
            shapes.list.forEach((item) => {
              item.render = item.select ? item.pre : item.draw;
            });
            shapes.render(ctx);
            shapes.curIndex = -1;
          }
          return;
        }
        if (shapes.isDraging) {
          // 拖动老图形
          console.log("拖动图形");
          const curentShape = shapes.list[shapes.curIndex];
          // 计算偏移量
          const dx = x - shapes.startX;
          const dy = y - shapes.startY;
          console.log("拖动老图形", dx, dy);
          // 移动
          curentShape.move(dx, dy);
          // 绘制移动后的图形
          shapes.render(ctx);
          // 更新起始点
          shapes.startX = x;
          shapes.startY = y;
        } else if (shapes.stretch) {
          // 拉伸图形
          // console.log("拉伸图形");
          const curentShape = shapes.list[shapes.curIndex];
          // 重复计算线段辅助线方向
          if (isResizing && curentShape.shape === "line") {
            // 区分直线
            const { direction } = curentShape.stretchDirection({ x, y });
            resizeDirection = direction;
            console.log("resizeDirection", resizeDirection);
          }
          let newShapePoints = curentShape.stretch({
            direction: resizeDirection,
            stretchPoint: { x, y },
          });
          // console.log("newShapePoints", newShapePoints);
          // 保存属性
          const savePropertyKeys = [
            "text",
            "textColor",
            "strokeColor",
            "fillColor",
            "font",
          ];
          savePropertyKeys.forEach((key) => {
            if (curentShape[key]) {
              newShapePoints[key] = curentShape[key];
            }
          });
          const newShape = new shapes[curentShape.shape]({
            ...newShapePoints,
            ...curentShape,
          });
          newShape.direction = resizeDirection;
          newShape.render = newShape.pre;
          const listkey =
            curentShape.shape === "text" ? "textList" : "shapeList";
          const i = shapes[listkey].findIndex((item) => item === curentShape);
          shapes[listkey].splice(i, 1, newShape);
          // console.log("shapes.list", shapes.list);
          shapes.render(ctx);
        }
      });
      c1.addEventListener("mouseup", () => {
        shapes.isStart = false;
        shapes.isDraging = false;
      });
      // 监控键盘删除键
      document.addEventListener("keydown", (e) => {
        const key = e.key || e.keyCode;
        console.log("key", key);
        if (
          key === "Backspace" ||
          key === "Delete" ||
          key === 8 ||
          key === 46
        ) {
          // 删除图形
          if (shapes.curIndex > -1) {
            const curentShape = shapes.list[shapes.curIndex];
            const listkey =
              curentShape.shape === "text" ? "textList" : "shapeList";
            const i = shapes[listkey].findIndex((item) => item === curentShape);
            shapes[listkey].splice(i, 1);
            shapes.render(ctx);
            shapes.curIndex = -1;
            c1.style.cursor = "default";
          }
        }
      });
      document.addEventListener("copy", function (event) {
        // 阻止默认的复制行为
        event.preventDefault();

        console.log("复制", shapes.curIndex);
        const copyShape = shapes.list[shapes.curIndex];
        // 复制图形
        const {
          startX,
          startY,
          endX,
          endY,
          strokeColor,
          fillColor,
          textColor,
        } = copyShape;
        const newShape = new copyShape.constructor({
          startX: startX + 10,
          startY: startY + 10,
          endX: endX + 10,
          endY: endY + 10,
          strokeColor,
          fillColor,
          textColor,
        });
        const listkey = copyShape.shape === "text" ? "textList" : "shapeList";
        shapes[listkey].push(newShape);
        shapes.render(ctx);
      });
    </script>
  </body>
</html>
